package com.autumn.mybatis.factory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import com.autumn.mybatis.provider.AutoProvider;
import com.autumn.mybatis.provider.IDbProvider;
import com.autumn.mybatis.provider.ProviderDriveType;
import com.autumn.util.ExceptionUtils;
import com.autumn.util.NumberUtils;
import com.autumn.util.StringUtils;
import com.autumn.util.TypeUtils;
import com.autumn.util.reflect.ReflectUtils;

/**
 * 动态属性数据源抽象
 * 
 * @author 老码农
 *         <p>
 *         Description
 *         </p>
 * @date 2017-12-30 10:35:52
 */
public abstract class AbstractDynamicDataSourceFactory implements IDataSourceFactory {

	/**
	 * 默认连接池
	 */
	public static final String DATA_SOURCE_TYPE_DEFAULT = "com.alibaba.druid.pool.DruidDataSource";

	/**
	 * 默认连接池
	 */
	public static final String DATA_SOURCE_DRIVER_DEFAULT = "com.mysql.jdbc.Driver";

	/**
	 * 创建数据源
	 * 
	 * @param dataSourcePropertiesMap
	 *            数据源属性Map
	 * @param provider
	 *            驱动提供者
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected DataSource createDataSource(Map<String, Object> dataSourcePropertiesMap, IDbProvider provider) {
		Map<String, Object> map = new HashMap<>(NumberUtils.MAP_LIST_DEFAULT_SIZE);
		for (Map.Entry<String, Object> entry : dataSourcePropertiesMap.entrySet()) {
			if (entry.getKey() != null) {
				map.put(StringUtils.configurePropertieName(entry.getKey()), entry.getValue());
			}
		}
		Object url = map.get("url");
		if (url == null || StringUtils.isNullOrBlank(url.toString().trim())) {
			throw ExceptionUtils.throwConfigureException("数据源未配置  url 属性");
		}
		ProviderDriveType driveType = ProviderDriveType.getDriveTypeForUrlPrefix(url.toString());
		if (driveType != null && driveType.getDefaultProviderType() != null && provider instanceof AutoProvider) {
			try {
				IDbProvider newDbProvider = driveType.getDefaultProviderType().newInstance();
				AutoProvider autoProvider = (AutoProvider) provider;
				autoProvider.setDbProvider(newDbProvider);
			} catch (Exception e) {
				throw ExceptionUtils.throwConfigureException(e.getMessage(), e);
			}
		}
		Object type = map.get("type");
		if (type == null || StringUtils.isNullOrBlank(type.toString().trim())) {
			type = DATA_SOURCE_TYPE_DEFAULT;
		}
		Object driverClass = map.get("driverClassName");
		if (driverClass == null || StringUtils.isNullOrBlank(driverClass.toString().trim())) {
			if (driveType != null && !driveType.equals(ProviderDriveType.CUSTOM)) {
				driverClass = ProviderDriveType.getFirstLoaderDriverClassName(driveType);
				if (driverClass == null) {
					throw ExceptionUtils
							.throwConfigureException("未搜索到 " + driveType.toString() + " 的驱动类型(driverClassName)。");
				}
			} else {
				driverClass = DATA_SOURCE_DRIVER_DEFAULT;
			}
		}
		try {
			Class<? extends DataSource> dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
			DataSource ds = dataSourceType.newInstance();
			map.remove("type");
			map.put("driverClassName", driverClass);
			Map<String, Method> methodMap = ReflectUtils.findPropertiesSetMethodMap(dataSourceType);
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				Method setMethod = methodMap.get(entry.getKey());
				if (entry.getValue() != null && setMethod != null) {
					String value = entry.getValue().toString().trim();
					if (!StringUtils.isNullOrBlank(value)) {
						setMethod.invoke(ds, TypeUtils.toConvert(setMethod.getParameterTypes()[0], value));
					}
				}
			}
			return ds;
		} catch (Exception e) {
			throw ExceptionUtils.throwConfigureException(e.getMessage(), e);
		}
	}
}
